package com.anclick.mywatch;
//
/*
 * [2011/04/19]
 * 1.시간 업데이트 체크를 1초에 한번씩 수행 후 변경 시 업데이트를 수행하는 방식에서
 *		한번 수행 후 다음번 업데이트를 60초 후로 설정하는 방법으로 변경
 *		(위젯 업데이트를 서비스를 사용하는 방법도 있으나 AlarmManager를 사용하는 방법이 자원을 덜 사용할 것으로 판단됨)
 * 2.manifest intent-filter와 onReceive함수 수정으로 최초 시간 업데이트를 수행하는 상활 고려=>잘 안됨
 * 		1)
 */

import java.io.*;
import java.text.*;
import java.util.*;

import android.app.*;
import android.appwidget.*;
import android.content.*;
import android.content.res.Resources;
import android.net.*;
import android.os.*;
import android.util.Log;
import android.widget.*;

/**
 * AppWidgetProvider를 상속받은 Class로 broascast 형태로 다른 component 들과 통신을 한다.
 * (AppWidgetProvider가 BroadcastReceiver를 상속하였기 때문)
 * AppWidget이 update, enabled, disabled, delete 되었을 때 broadcast 형태로 callback이 불린다.
 * 
 * com.anclick.mywatch
 * MyWatchProvider.java
 *
 * @author junhwan_kim
 * @date 2011. 4. 29. 오후 2:16:51
 * @Version
 */
public class MyWatchProvider extends AppWidgetProvider {

	private static final String TAG = "MyWatch";
	private static String mDateFormat = "EEE MMM dd yyyy hh mm a";	/// 요일 월 일 년 시 분 APM
	
	/**
	 * Called in response to the ACTION_APPWIDGET_UPDATE broadcast when this AppWidget provider is being asked to provide RemoteViews for a set of AppWidgets. 
	 * AppWidget의 속성(Meta data)에서 지정해준 updatePeriodMillis 값에 따라 주기적으로 호출된다.
	 * 또한 처음 widget이 화면에 붙을 때, init() 작업을 해주기 위해서도 call 된다.
	 * (Configuration activity를 따로 두었다면, 처음 붙을 때 불리지는 않음. 대신 Configuration Activity가 init를 함.)
	 * 
	 * @see android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[])
	 * @Method onUpdate
	 * @param context
	 * @param appWidgetManager
	 * @param appWidgetIds
	 *
	 * @author junhwan_kim
	 * @date 2011. 4. 29. 오후 2:16:56
	 */
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
		/// widget id 쓰도록 변경, 2011.05.06, junhwan_kim
		final int N = appWidgetIds.length;
        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];
            Log.d(TAG, "onUpdate(" + appWidgetId + ")");
            updateWidget(context, appWidgetManager, appWidgetId);
        }
        
        super.onUpdate(context, appWidgetManager, appWidgetIds);
	}
	
	/**
	 * Implements onReceive(Context, Intent) to dispatch calls to the various other methods on AppWidgetProvider.
	 * 일반적인 broadcasting receiver
	 * 다른 callback들 보다 먼저 불림.
	 * 
	 * @see android.appwidget.AppWidgetProvider#onReceive(android.content.Context, android.content.Intent)
	 * @Method onReceive
	 * @param context
	 * @param intent
	 *
	 * @author junhwan_kim
	 * @date 2011. 4. 29. 오후 2:17:00
	 */
	@Override
	public void onReceive(Context context, Intent intent) {
		Log.i(TAG, "onReceive()");
		
		/// TIME_TICK broadcast를 받는 경우 widget을 update하도록 수정, 2011.05.03, junhwan_kim
		context.startService(new Intent(context, MyWatchService.class));
		
		String action = intent.getAction();
        if (action.equals(Intent.ACTION_TIME_TICK)) {
        	Log.d(TAG, "ACTION_TIME_TICK");
        	
        	AppWidgetManager gm = AppWidgetManager.getInstance(context);

        	Map<String,?> map = MyWatchPreferences.getAllWidgetId(context);	// widget id를 map으로 가져온다.
            Set<String> set = map.keySet();		// hm의 키값들을 Set(집합)으로 값을 가져옵니다.
            Object []hmKeys = set.toArray();	// Set의 값들을 Object 배열로 변환합니다.
            
            // Object 배열의 요소(키값이죠.)이걸로 hm의 값을 가져와서 출력합니다.
            for(int i =  0; i < hmKeys.length; i++) {
                String key = (String)hmKeys[i];
                updateWidget(context, gm, Integer.parseInt(key));
            }
            
//        	/// 등록된 모든 widget id를 가져와서 update한다.(시간 갱신때문), 2011.05.06, junhwan_kim 
//        	Map<String,?> map = MyWatchPreferences.getWidgetId(context);
//        	Log.d(TAG, "ACTION_TIME_TICK(" + map + ")");
//        	
//        	map.keySet().toArray();
//        	Iterator<String> it = map.keySet().iterator();
//        	while(it.hasNext()) {
//        		updateWidget(context, gm, Integer.parseInt(it.next()));
//        	}
        }
        
        super.onReceive(context, intent);
	}

	/**
	 * Called in response to the ACTION_APPWIDGET_ENABLED broadcast when the a AppWidget for this provider is instantiated. 
	 * App Widget이 처음 생성될 때 불린다.
	 * 같은 위젯을 여러개 띄우면, 첫번째 위젯을 띄울 때만 호출이 된다.
	 * 
	 * @see android.appwidget.AppWidgetProvider#onEnabled(android.content.Context)
	 * @Method onEnabled
	 * @param context
	 *
	 * @author junhwan_kim
	 * @date 2011. 4. 29. 오후 2:17:06
	 */
	@Override
	public void onEnabled(Context context) {
		Log.i(TAG, "onEnabled()");

		super.onEnabled(context);
	}

	/**
	 * Called in response to the ACTION_APPWIDGET_DELETED broadcast when one or more AppWidget instances have been deleted. 
	 * App Widget이 Widget host로 부터 삭제될 때 불린다.
	 * 
	 * @see android.appwidget.AppWidgetProvider#onDeleted(android.content.Context, int[])
	 * @Method onDeleted
	 * @param context
	 * @param appWidgetIds
	 *
	 * @author junhwan_kim
	 * @date 2011. 4. 29. 오후 2:17:11
	 */
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		/// 해당 id를 삭제한다., 2011.05.06, junhwan_kim
		final int N = appWidgetIds.length;
        for (int i=0; i<N; i++) {
        	Log.d(TAG, "onDeleted(" + appWidgetIds[i] + ")");
        	MyWatchPreferences.removePref(context, appWidgetIds[i]);
        	MyWatchPreferences.removeWidgetId(context, appWidgetIds[i]);
        }
        
        super.onDeleted(context, appWidgetIds);
	}

	/**
	 * Called in response to the ACTION_APPWIDGET_DISABLED broadcast, which is sent when the last AppWidget instance for this provider is deleted. 
	 * App Widget이 삭제될 때 불린다.
	 * 가장 마지막에 남아있는 App Widget이 detach 되었을 때 호출된다.
	 * 
	 * @see android.appwidget.AppWidgetProvider#onDisabled(android.content.Context)
	 * @Method onDisabled
	 * @param context
	 *
	 * @author junhwan_kim
	 * @date 2011. 4. 29. 오후 2:17:15
	 */
	@Override
	public void onDisabled(Context context) {
		Log.i(TAG, "onDisabled()");

		/// 추가된 앱 위젯별로 설정한 디렉토리 정보 초기화
		MyWatchPreferences.removeAllPref(context);
		MyWatchPreferences.removeAllWidgetId(context);
		super.onDisabled(context);
	}

	/**
	 * AppWidget에 뿌려질 뷰를 업데이트
	 * 
	 * @Method updateWidget
	 * @param context
	 * @param bForce
	 *
	 * @author junhwan_kim
	 * @date 2011. 4. 29. 오후 2:17:20
	 */
	static public void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
		
		///★★★본 Provider로 여러개의 앱위젯 인스턴스 생성 시 각각의 인스턴스가 동시에 업데이트 되기 위해선
		///	각각의 업데이트를 독립된 Thread로 처리해야 한다.
		///	이러한 문제는 에니메이션이 적용되는 경우에 더욱 필요하다.
		
		SimpleDateFormat sdf = new SimpleDateFormat(mDateFormat, Locale.US);
		String sDate = sdf.format(new Date());
		
		Log.d(TAG, "updateWidget(" + appWidgetId + ")");
		
		int imageCount = 0;
		
		/// 요일 월 일 년 시 분 APM
		String aDateTime[] = sDate.split(" ");	/// ex) "Tue May 03 2011 03 52
		
		String sDayOfWeek = aDateTime[0].toLowerCase();		/// 요일
		String sMonth = aDateTime[1].toLowerCase();			/// 월
		String sDay10 = aDateTime[2].substring(0, 1);		/// 일1
		String sDay01 = aDateTime[2].substring(1, 2);		/// 일2
		String sYear = aDateTime[3];						/// 년
		String sHour10 = aDateTime[4].substring(0, 1);		/// 시1
		String sHour01 = aDateTime[4].substring(1, 2);		/// 시2
		String sMin10 = aDateTime[5].substring(0, 1);		/// 분1
		String sMin01 = aDateTime[5].substring(1, 2);		/// 분2
		String sAmPm = aDateTime[6].toLowerCase();			/// AMPM
		
		String[] prefValue = MyWatchPreferences.getPref(context, appWidgetId);
		
		/// 선택된 디렉토리 없을 때 대비
		File sSDPath = Environment.getExternalStorageDirectory();
		String directory = prefValue[MyWatchPreferences.IMAGEPATH];
		Log.d(TAG, "update widgetid : "+appWidgetId);
		String fullDirectory = sSDPath.getAbsolutePath() + MyWatchConfigure.SUB_PATH + "/" + directory;

		/// 이미지 카운트를 체크하는 코드 => 디렉토리 선택 시 체크해 저장하는 방식으로 변경해야 함
		/// 애니매이션 처리부분 
		/// !!루프를 언제까지 돌릴건지?
		for(int i = 0; i < 100; i++){
			File fileTmp = new File(fullDirectory + "/num_0_" + i + ".png");
			if(!fileTmp.isFile()){
				imageCount = i;
				break;
			}
		}
		
		/// Onclick Intent 등록 및 Widget ID 전달.
        Intent intent = new Intent(context, MyWatchConfigure.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        intent.putExtra("SELECTED_WIDGET_ID", appWidgetId);
         
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);
        //PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);	//★★★★★ 무지중요
        PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.appwidgetlayout, pendingIntent);
                                                          
		/// SDCard에 이미지 없는 경우 
        if (directory.equals("My Watch")) {
        	
        	Resources res = context.getResources();
        	
        	views.setImageViewResource(R.id.imgHour10, res.getIdentifier("num_" + sHour10 + "_0", "drawable", context.getPackageName()));	// 10시간 단위 표시 뷰
        	views.setImageViewResource(R.id.imgHour01, res.getIdentifier("num_" + sHour01 + "_0", "drawable", context.getPackageName()));	// 01시간 단위 표시 뷰
        	views.setImageViewResource(R.id.imgColon, R.drawable.colon);																// colon
        	views.setImageViewResource(R.id.imgMinute10, res.getIdentifier("num_" + sMin10 + "_0", "drawable", context.getPackageName()));	// 10분 단위 표시 뷰
        	views.setImageViewResource(R.id.imgMinute01, res.getIdentifier("num_" + sMin01 + "_0", "drawable", context.getPackageName()));	// 01분 단위 표시 뷰
        	
        	/// AM/PM on/off
			if (prefValue[MyWatchPreferences.AMPM].equals("1")) {
				views.setImageViewResource(R.id.imgAPM, res.getIdentifier(sAmPm, "drawable", context.getPackageName()));	// AM PM 표시 뷰.
			} else {
				views.setImageViewResource(R.id.imgAPM, R.drawable.dummy);
			}
			
			/// Date on/off
			if (prefValue[MyWatchPreferences.DATE].equals("1")) {
				/// Month
				views.setImageViewResource(R.id.imgMonth, res.getIdentifier("month_" + sMonth, "drawable", context.getPackageName()));	// Month 표시 뷰

				/// Date
				views.setImageViewResource(R.id.imgDay10, res.getIdentifier("number_bold_0" + sDay10, "drawable", context.getPackageName()));	// date1 표시 뷰
				views.setImageViewResource(R.id.imgDay01, res.getIdentifier("number_bold_0" + sDay01, "drawable", context.getPackageName()));	// date2 표시 뷰
				
				/// Day of week
				views.setImageViewResource(R.id.imgDayOfWeek, res.getIdentifier("week_" + sDayOfWeek, "drawable", context.getPackageName()));	// day of week 표시 뷰
				
				/// Year
				views.setImageViewResource(R.id.imgYear, res.getIdentifier("year_" + sYear, "drawable", context.getPackageName()));	// day of week 표시 뷰
			} else {
				views.setImageViewResource(R.id.imgMonth, R.drawable.dummy);
				views.setImageViewResource(R.id.imgDay10, R.drawable.dummy);
				views.setImageViewResource(R.id.imgDay01, R.drawable.dummy);
				views.setImageViewResource(R.id.imgDayOfWeek, R.drawable.dummy);
				views.setImageViewResource(R.id.imgYear, R.drawable.dummy);
			}
			
//			/// Day of week on/off
//			if (prefValue[WidgetPreferences.DAYOFWEEK].equals("1")) {
//				views.setImageViewResource(R.id.imgDayOfWeek, res.getIdentifier("week_" + sDayOfWeek, "drawable", context.getPackageName()));	// day of week 표시 뷰
//			} else {
//				views.setImageViewResource(R.id.imgDayOfWeek, R.drawable.dummy);
//			}
			
			/// Background on/off
			if (prefValue[MyWatchPreferences.BACKGROUND].equals("1")) {
				views.setInt(R.id.appwidgetlayout, "setBackgroundResource", R.drawable.background);	// Background 표시 뷰
			} else {
				views.setInt(R.id.appwidgetlayout, "setBackgroundResource", R.drawable.dummy);
			}
			
			appWidgetManager.updateAppWidget(appWidgetId, views);
        } 
        /// SDCard에 이미지 있는 경우
        else {
			views.setImageViewUri(R.id.imgHour10, Uri.fromFile(new File(fullDirectory + "/num_" + sHour10 + "_" + (imageCount - 1) + ".png")));	//10시간 단위 표시 뷰
			views.setImageViewUri(R.id.imgHour01, Uri.fromFile(new File(fullDirectory + "/num_" + sHour01 + "_" + (imageCount - 1)  + ".png")));	//01시간 단위 표시 뷰
			views.setImageViewUri(R.id.imgColon, Uri.fromFile(new File(fullDirectory + "/colon.png")));
			views.setImageViewUri(R.id.imgMinute10, Uri.fromFile(new File(fullDirectory + "/num_" + sMin10 + "_" + (imageCount - 1)  + ".png")));	//10분 단위 표시 뷰
			views.setImageViewUri(R.id.imgMinute01, Uri.fromFile(new File(fullDirectory + "/num_" + sMin01 + "_" + (imageCount - 1)  + ".png")));	//01분 단위 표시 뷰
			
			/// AM/PM on/off
			if (prefValue[MyWatchPreferences.AMPM].equals("1")) {
				views.setImageViewUri(R.id.imgAPM, Uri.fromFile(new File(fullDirectory + "/" + sAmPm + ".png")));
			} else {
				views.setImageViewUri(R.id.imgAPM, Uri.fromFile(new File(fullDirectory + "/dummy.png")));
			}
			
			/// Date on/off
			if (prefValue[MyWatchPreferences.DATE].equals("1")) {
				views.setImageViewUri(R.id.imgMonth, Uri.fromFile(new File(fullDirectory + "/month_" + sMonth + ".png")));
				views.setImageViewUri(R.id.imgDay10, Uri.fromFile(new File(fullDirectory + "/number_bold_0" + sDay10 + ".png")));
				views.setImageViewUri(R.id.imgDay01, Uri.fromFile(new File(fullDirectory + "/number_bold_0" + sDay01 + ".png")));
				views.setImageViewUri(R.id.imgDayOfWeek, Uri.fromFile(new File(fullDirectory + "/week_" + sDayOfWeek + ".png")));
				views.setImageViewUri(R.id.imgYear, Uri.fromFile(new File(fullDirectory + "/year_" + sYear + ".png")));
			} else {
				views.setImageViewUri(R.id.imgMonth, Uri.fromFile(new File(fullDirectory + "/dummy.png")));
				views.setImageViewUri(R.id.imgDay10, Uri.fromFile(new File(fullDirectory + "/dummy.png")));
				views.setImageViewUri(R.id.imgDay01, Uri.fromFile(new File(fullDirectory + "/dummy.png")));
				views.setImageViewUri(R.id.imgDayOfWeek, Uri.fromFile(new File(fullDirectory + "/dummy.png")));
				views.setImageViewUri(R.id.imgYear, Uri.fromFile(new File(fullDirectory + "/dummy.png")));
			}
			
//			/// Day of week on/off
//			if (prefValue[WidgetPreferences.DAYOFWEEK].equals("1")) {
//				views.setImageViewUri(R.id.imgDayOfWeek, Uri.fromFile(new File(fullDirectory + "/week_" + sDayOfWeek + ".png")));
//			} else {
//				views.setImageViewUri(R.id.imgDayOfWeek, Uri.fromFile(new File(fullDirectory + "/dummy.png")));
//			}
			
			/// !!!SDCARD에서 이미지를 불러와 배경에 지정하는 코드는 더 생각해봐야함.
//			/// Background on/off
//			if (prefValue[WidgetPreferences.BACKGROUND].equals("1")) {
//				Drawable drawable = Drawable.createFromPath(fullDirectory + "/background.png");
//				Bitmap bitmap = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
//				Canvas canvas = new Canvas(bitmap);
//				drawable.setBounds(0, 0, 150, 150);
//				drawable.draw(canvas);
//				
//				views.setBitmap(R.id.appwidgetlayout, "setBackgroundDrawable", bitmap);
//			} else {
//				Drawable drawable = Drawable.createFromPath(fullDirectory + "/dummy.png");
//				Bitmap bitmap = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
//				Canvas canvas = new Canvas(bitmap);
//				drawable.setBounds(0, 0, 150, 150);
//				drawable.draw(canvas);
//				
//				views.setBitmap(R.id.appwidgetlayout, "setBackgroundDrawable", bitmap);
//			}
			
			/// Background on/off
			if (prefValue[MyWatchPreferences.BACKGROUND].equals("1")) {
				views.setInt(R.id.appwidgetlayout, "setBackgroundResource", R.drawable.background1);	// Background 표시 뷰
			} else {
				views.setInt(R.id.appwidgetlayout, "setBackgroundResource", R.drawable.dummy);
			}
			
			/// Animation on/off
//			if (prefValue[WidgetPreferences.ANIMATION].equals("1")) {
				if (imageCount > 1) {
					for (int i = 0; i < imageCount; i++) {
						try {
							/// sHour10이 애니메이션 될 경우
							if (sHour01.equals("0") && sMin10.equals("0") && sMin01.equals("0")) {
								views.setImageViewUri(R.id.imgHour10, Uri.fromFile(new File(fullDirectory + "/num_" + sHour10 + "_" + i + ".png")));
							}
							/// sHour01이 애니메이션 될 경우
							if (sMin10.equals("0") && sMin01.equals("0")) {
								views.setImageViewUri(R.id.imgHour01, Uri.fromFile(new File(fullDirectory + "/num_" + sHour01 + "_" + i + ".png")));
							}
							/// sMin10이 애니메이션 될 경우
							if (sMin01.equals("0")) {
								views.setImageViewUri(R.id.imgMinute10, Uri.fromFile(new File(fullDirectory + "/num_" + sMin10 + "_" + i + ".png")));
							}
							/// sMin01이 애니메이션 될 경우
							views.setImageViewUri(R.id.imgMinute01, Uri.fromFile(new File(fullDirectory + "/num_" + sMin01 + "_" + i + ".png")));
							
							appWidgetManager.updateAppWidget(appWidgetId, views);
							Thread.sleep(150);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					} 
				} else {
					appWidgetManager.updateAppWidget(appWidgetId, views);
				}
//			} else {
//				appWidgetManager.updateAppWidget(appWidgetId, views);
//			}
        }
	}
}
